package mandreelFile;

import Class.ImandreelCtxCanvas;
import Class.LZMA;
import Class.MandreelElement.MandreelBase;
import Class.MandreelElement.MandreelElement;
import Class.MouseEvent;
import Class.SwfObject.Param;
import Main.Timer;
import commonFile.ArrayUniformLocations;
import commonFile.TlsfPtr;
import mandreelFile1.mandreelFile1;

import javax.swing.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;

import static Class.CommonClassFile.commonVariable;
import static Class.CommonClassFile.heapClassInst;
import static Class.DevNumber.*;
import static Class.LZMA.lzMA;
import static Class.MandreelDocument.mandreelDocument;
import static Class.MandreelWindow.GetItemARR;
import static Class.MandreelWindow.mandreelWindow;
import static Class.SwfObject.swfObject;
import static commonFile.CommonFile.*;
import static mandreelFile1.mandreelFile1.*;
import static mandreelFile10.mandreelFile10.globalInit2;
import static mandreelFile11.mandreelFile11.globalInit3;
import static mandreelFile12.mandreelFile12.globalInit4;
import static mandreelFile13.mandreelFile13.globalInit5;
import static mandreelFile14.mandreelFile14.globalInit6;
import static mandreelFile15.mandreelFile15.globalInit7;
import static mandreelFile15.mandreelFile15.swriteIndexInitialize;
import static mandreelFile7.mandreelFile7.*;
import static mandreelFile8.mandreelFile8.globalInit;
import static mandreelFile9.mandreelFile9.globalInit1;

public class mandreelFile {

    public static class HeapValue {
        int l = 0;
        int h = 0;
    }

    public static class MandreelEmbedPlugin {
        public void mandreelInterCalls(String str1, int... ptr) {

        }
    }

    public static class Navigatortype {
        public String appName = "";
        public String userAgent = "";
    }

    static Param gMandreelSwf = null;

    public static class MandInt {
        public Param mandreelInterGetSWF() {
            if (mandreelFile.gMandreelSwf != null) {
                return mandreelFile.gMandreelSwf;
            }
            Param gMandreelSwf = swfObject.getObjectById(mandreelFile.mandreelAppCanvasDiv);
            return gMandreelSwf;
        }
    }

    public static class GetSwf extends MandInt {
        public GetSwf() {
            super();
            this.mandreelInterGetSWF();
        }

        public int mandreelInterGetGlobalStack() {
            return 1;
        }

        public int mandreelInterGetGlobalStack2() {
            return 1;
        }

        public String mandreelInterCallFunctionRaw(int x, String y, String z) {
            return " ";
        }
    }

    public static class MandreelXMLHttpRequest {
        public String url = "";
        public String response = null;
        public Integer readyState = null;
        public Integer status = null;
        public Runnable onreadystatechange = () -> {
        };

        public MandreelXMLHttpRequest(String url) {
            this.url = url;
        }

        public void open(String type, String url, boolean someBool) {
            this.url = url;
        }

        public void overrideMimeType() {

        }

        public void send() {
            this.response = null;
            this.readyState = numDefine4;
            this.status = 0;
        }
    }

    public static class Resxy {
        public int x = 0;
        public int y = 0;
    }

    public static class FunClass {
        public String funcName = "";
        public String param = "";

        public FunClass(String funcName, String param) {
            this.funcName = funcName;
            this.param = param;
        }
    }

    public static class ReadWrite {
        public String readWrite = "";
    }

    public static class MandreelindexedDB {
        public DbClass db = new DbClass();
        public boolean callbackInit;

        public MandreelindexedDB(DbClass db, boolean callbackInit) {
            this.db = db;
            this.callbackInit = callbackInit;
        }

        public void onerror(String e) {
            System.out.println(e);
        }
    }

    public static class DbClass {
        public Dbtrans transaction(String[] cache, String type) {
            return new Dbtrans();
        }
    }

    public static class Dbtrans {
        public DbRequest objectStore(String cache) {
            return new DbRequest();
        }
    }

    public static class DbRequest {
        public Request put(String param) {
            return new Request();
        }

        public Request get(String key) {
            return new Request();
        }
    }

    public static class Request {
        public void onsuccess(String e) {
            System.out.println("mandreelIndexedDB.save ok");
        }

        public void onerror(String e, String fileName) {
            System.out.println("mandreelIndexedDB.save onerror" + fileName);
            System.out.println(e);
        }

        public void createObjectStore(String name, String type) {

        }
    }

    public static class GetTime {
        public void getTime() {

        }
    }


    MandreelEmbedPlugin mandreelEmbedPlugin = new MandreelEmbedPlugin();
    int mandreelPluginCurrentSp = 0;

    int mandreelHttpRequestModeGet = 0;
    int mandreelHttpRequestModePost = 1;
    int mandreelHttpRequestModePut = numDefine2;

    int mandreelhttprequeststatuserror = 0;
    int mandreelhttprequeststatusbusy = 1;
    int mandreelhttprequeststatusfinished = numDefine2;
    int mandreelhttprequeststatusinit = numDefine3;
    double mandeelLog10 = numDefineFloatLog346;

    ArrayList<Integer> mandreelJsMappingIdsFree = new ArrayList<Integer>();

//    static Consumer<int[]> myOldConstructors;
static MyConsumer<String, Object, Object> mandreelAppStartStateFunc;
    static boolean mandreelAppLog = false;
    static String mandreelAppWorkingFolder = "data/js/";
    static double mandreelAppWidthSrc = numDefine1024;
    static double mandreelAppHeightSrc = numDefine768;
    static boolean mandreelAppReadDataFromLocalHost = false;
    static String mandreelAppMandreelJs = "mandreel.js";
    static boolean mandreelAppMandreelJsCompressed = false;
    static String mandreelAppLocalHost = "http://localhost";

    static boolean mandreelAppReadMandreelJsFromLocalHost = false;
    static String mandreelAppHostedAudioServer = null;
    static String mandreelAppHostedAudioUrl = null;
    static String mandrelCurrentFatVersion = "1.4";

    static double mandreelAppCanvasWidth = numDefine1024;
    static double mandreelAppCanvasHeight = numDefine768;
    String mandreelappcanvasname = "canvas";
    static String mandreelAppCanvasDiv = "canvasDiv";
    static boolean mandreelAppUseFlashSockets = false;
    static ArrayList<String> mandreelAppUsePackAsyncTexture = new ArrayList<String>();
    boolean mandreelAppForceFocus = true;
    static boolean imandreelPauseGame = false;

    static MandreelXMLHttpRequest mandreelFatPreloadRequest = null;

    static String mandreelPackfiledataName = null;
    static boolean mandreelPackfiledataCompressed = false;
    static int mandreelPackfiledataSize = 0;
    static int mandreelTotalPacktextureSize = 0;
    int mandreelloadedpacktexturesize = 0;
    int mandreelJslzmaSize = 0;
    int mandreelSwfSize = 0;
    static ArrayList<Object> timeouts = new ArrayList<Object>();
    static boolean imandreelIsReady = false;
    static ArrayList<Integer> mandreeltimeouts = new ArrayList<Integer>();
    static boolean mandreelJsScriptLoadedLoaded = false;
    int mandreelswflasttotalsize = 0;
    static String mandreelCurrentPackTexture = "";
    int mandreelUpdateTotalSize = 0;
    String isieold = "";
    String isfirefoxnew = "";
    String ischrome = "";
    static long imandreelOldTime = 0;
    double imandreellastmovex = 0.0;
    double imandreellastmovey = 0.0;
    boolean mandreelmousedown = false;
    boolean mandreelrmousedown = false;

    static ImandreelCtxCanvas imandreelCtxCanvas = new ImandreelCtxCanvas();

    int maxOglId = numDefine8192;
    ArrayList<Integer> arrayIdsOglEnable = new ArrayList<Integer>();
    int gcurrentprogramid = 0;
    ArrayList<Double> uniformArrays2 = new ArrayList<Double>();
    ArrayList<Double> uniformArrays3 = new ArrayList<Double>();
    ArrayList<Double> uniformArrays4 = new ArrayList<Double>();
    int uniformArraysCreated = 0;
    boolean mandreeldrawenable = true;
    int mySuperId = 1;

    int imandreelFlashGlobalSp = 0;
    int imandreelFlashGlobalSp2 = 0;
    int imandreelflashcurrentsp = 0;

    boolean indexedDB = (mandreelWindow.indexedDB != 0) || (mandreelWindow.webKitIndexedDB != 0) || (mandreelWindow.mozIndexedDB != 0);


    GetSwf mandreelInterGetSWF = new GetSwf();

    ReadWrite iDBTransactions = new ReadWrite();
    int mandreelcalljsTypeReturnVoid = 0;
    int mandreelcalljsTypeInt = 1;
    int mandreelcalljsTypeFloat = numDefine2;
    int mandreelcalljsTypeString = numDefine3;
    int mandreelcalljsTypeReturnInt = numDefine4;
    int mandreelcalljsTypeReturnFloat = numDefine5;
    int mandreelTextureAsyncTextures = 0;
    int mandreelTextureAsyncTexturesLoaded = 0;
    ArrayList<Integer> glBufferDataArray = new ArrayList<Integer>();
    static ArrayList<FunClass> mandreelAsyncCallsMandreel = new ArrayList<FunClass>();
    static ArrayList<FunClass> mandreelAsyncCallsJs = new ArrayList<FunClass>();
    boolean gmandreelcachefiles = false;
    static boolean gMandreelFrameLocked = false;
    static boolean gMandreelFrameInframe = false;

    MandreelindexedDB mandreelIndexedDB = new MandreelindexedDB(null, true);

    public static void mandreelLoadFat() {
        String workingFolder = mandreelAppWorkingFolder;
        if (mandreelAppReadDataFromLocalHost) {
            workingFolder = mandreelAppLocalHost + "/" + mandreelAppWorkingFolder;
        }
        String url = workingFolder + "mandreel.fat.dat";
        mandreelFatPreloadRequest = new MandreelXMLHttpRequest(url);
        if (commonVariable.mandreelAppPlatform.equals("nacl")) {
            url = workingFolder + "mandreel.fat";
        }
        mandreelFatPreloadRequest.open("GET", url, true);
        mandreelFatPreloadRequest.onreadystatechange = new Runnable() {
            public void run() {
                if (mandreelFatPreloadRequest.readyState != numDefine4) {
                    return;
                }
                if (mandreelFatPreloadRequest.status != numDefine404 &&
                        mandreelFatPreloadRequest.response != null) {
                    commonVariable.mandreelFatData = mandreelFatPreloadRequest.response.toString();
                }
                if (commonVariable.mandreelFatData.equals("")) {
                    dump("error loading mandreel.fat file, Maybe the working folder is not correctly set???");
                }

                String packfiledata = null;
                boolean compressed = false;
                int packfiledataSize = 0;
                int totalPacktextureSize = 0;
                int pogsize = 0;

                String[] fatLines = commonVariable.mandreelFatData.split("\n");
                for (int i = 0; i < fatLines.length; i++) {
                    String line = mandreelRemovecr(fatLines[i]);
                    String[] params = line.split(",");
                    if (params[0].equals("version")) {
                        if (!params[1].equals(mandrelCurrentFatVersion)) {
                            dump("warning: mandreel.fat version number is (" +
                                    params[1] + ") and it should be (" + mandrelCurrentFatVersion + ")");
                        }
                    } else if (params[0].equals("platform") &&
                            !params[1].equals("js") &&
                            (commonVariable.mandreelAppPlatform.equals("webgl") ||
                                    commonVariable.mandreelAppPlatform.equals("canvas"))) {
                        dump("warning: mandreel.fat platform is (" + params[1] + ") and it should be (js)");
                    } else if (params[0].equals("platform") &&
                            !params[1].equals("nacl") &&
                            commonVariable.mandreelAppPlatform.equals("nacl")) {
                        dump("warning: mandreel.fat platform is (" + params[1] + ") and it should be (nacl)");
                    } else if (params[0].equals("packdata")) {
                        packfiledata = params[1];
                    } else if (params[0].equals("flashsockets")) {
                        mandreelAppUseFlashSockets = true;
                    } else if (params[0].equals("packtexture")) {
                        String filename = params[1];
                        mandreelAppUsePackAsyncTexture.add(filename);
                    } else if (params[0].equals("audiopreloadfile")) {

                    } else if (params[0].equals("audiodriver") && params[1].equals("webaudio")) {
                    }
                }

                if (variableSet.preCreatedWebAudioContext != null) {
                    variableSet.mandreelTotalPogfileSize = pogsize;
                    mandreelPackfiledataName = packfiledata;
                    mandreelPackfiledataCompressed = compressed;
                    mandreelPackfiledataSize = packfiledataSize;
                    mandreelTotalPacktextureSize = totalPacktextureSize;
                    mandreelFatLoaded();
                }
            }
        };
        mandreelFatPreloadRequest.send();
    }

    public static void mandreelAppStart(MyConsumer<String, Object, Object> startStateFunc, Param params) {
        mandreelAppStartStateFunc = startStateFunc;

        if (params.log) {
            mandreelAppLog = params.log;
        }

        if (!params.platform.isEmpty()) {
            commonVariable.mandreelAppPlatform = params.platform;
        }

        if (params.mandreelJSCompressed) {
            mandreelAppMandreelJsCompressed = params.mandreelJSCompressed;
        }

        if (!commonVariable.mandreelAppPlatform.equals("webgl") &&
                !commonVariable.mandreelAppPlatform.equals("flash") &&
                !commonVariable.mandreelAppPlatform.equals("nacl") &&
                !commonVariable.mandreelAppPlatform.equals("canvas") &&
                !commonVariable.mandreelAppPlatform.equals("plugin")) {
            mandreelAppStartStateFunc.accept("error", "platform (" + commonVariable.mandreelAppPlatform + ") not supported", null);
            return;
        }

        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            mandreelAppWorkingFolder = "data/js/";
            if (!params.workingFolderWebgl.isEmpty()) {
                mandreelAppWorkingFolder = params.workingFolderWebgl;
            }

            if (!(mandreelWindow.float64Array.length != 0)) {
                mandreelAppStartStateFunc.accept("error", "Browser unsupported" + "Float64Array not available", null);
                return;
            }

            MandreelBase flashElement = mandreelDocument.getElementById("FlashDiv");
            if (flashElement != null) {
                flashElement.style.visibility = "hidden";
                flashElement.style.width = "0px";
                flashElement.style.height = "0px";
            }

            if (params.webglCanvas.isEmpty()) {
                mandreelAppStartStateFunc.accept("error", "canvas parameter not found", null);
                return;
            }
            MandreelBase canvas = mandreelDocument.getElementById(params.webglCanvas);
            if (canvas == null) {
                mandreelAppStartStateFunc.accept("error", "canvas object (" + params.webglCanvas + ") not found", null);
                return;
            }

            if (params.width != 0) {
                canvas.width = params.width;
                mandreelAppWidthSrc = params.width;
            }

            if (params.height != 0) {
                canvas.height = params.height;
                mandreelAppHeightSrc = params.height;
            }
            if (commonVariable.mandreelAppPlatform.equals("webgl")) {
            }

            if (commonVariable.mandreelAppPlatform.equals("canvas")) {
                imandreelCtxCanvas = canvas.getContext("2d");
                if (imandreelCtxCanvas == null) {
                    mandreelAppStartStateFunc.accept("error", "canvas context numDefine2d not found", null);
                    return;
                }
            }
            if (params.cache != null) {
            } else {
                if (mandreelAppStartStateFunc != null) {
                    mandreelAppStartStateFunc.accept("loadingFat", "", null);
                }
                mandreelLoadFat();
            }
        }
        if (commonVariable.mandreelAppPlatform.equals("flash")) {
            mandreelAppWorkingFolder = "data/as3/";
            if (params.workingFolderFlash != null) {
                mandreelAppWorkingFolder = params.workingFolderFlash;
            }

            if (!swfObject.hasFlashPlayerVersion("11.2.0")) {
                mandreelAppStartStateFunc.accept("error", "flash numDefine11 not found", null);
                return;
            }

            if (params.flashCanvas != null) {
                mandreelAppStartStateFunc.accept("error", "canvas parameter not found", null);
                return;
            }

            if (true) {
                MandreelBase canvas = mandreelDocument.getElementById(mandreelAppCanvasDiv);
                if (canvas != null) {
                    canvas.style.visibility = "hidden";
                    canvas.style.width = "0px";
                    canvas.style.height = "0px";
                }
            }

            if (params.width != 0) {
                mandreelAppCanvasWidth = params.width;
            }

            if (params.height != 0) {
                mandreelAppCanvasHeight = params.height;
            }

            mandreelAppCanvasDiv = params.flashCanvas;

            String mandreelSocketsSwf = "mandreel.swf";
            try {
                if (params.swfFlash != null) {
                    mandreelSocketsSwf = params.swfFlash;
                }

                String myFlashvars = "workingFolder=";
                if (params.log) {
                    myFlashvars += "&log=true";
                    myFlashvars += "&width=" + params.width;
                    myFlashvars += "&height=" + params.height;
                    myFlashvars += "&swfloader=" + mandreelSocketsSwf;
                }
                if (params.restoreContext) {
                    myFlashvars += "&restoreContext=1";
                }

                if (params.antialiasing != 0) {
                    myFlashvars += "&antialiasing=" + params.antialiasing;
                }

                if (params.rightClickEnable) {
                    myFlashvars += "&rightClick=1";
                }

                if (params.disableDepth) {
                    myFlashvars += "&disableDepth=1";
                }

                String swfname = "mandreelloader.swf";
                if (!params.swfPreloader) {
                    swfname = mandreelSocketsSwf;
                }
            } catch (Exception err) {
                mandreelAppStartStateFunc.accept("error", "exception while loading " + mandreelSocketsSwf, null);
                return;
            }

            appStartState("loadingScript", null);
        }
        if (commonVariable.mandreelAppPlatform.equals("nacl")) {
            mandreelAppWorkingFolder = "data/nacl/";

            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingFat", "", null);
            }
            mandreelLoadFat();
        }

        if (commonVariable.mandreelAppPlatform.equals("plugin")) {
            mandreelInitPluginPlatform(params);
        }
    }

    public static void startApp(String platform) {
        Param params = new Param(platform);
        mandreelAppStart(mandreelFile::appStartState, params);
    }

    public static void mandreelAppStartRenderWebGL() {
        mandreelAppInit();
        imandreelIsReady = true;
    }

    public static void mandreelAppStartReady() {
        if (commonVariable.mandreelAppPlatform.equals("nacl")) {
            new mandreelFile1().waInitWebAudio();
            new mandreelFile1().mandreelWebAudioPreloadAssets();
        } else {
            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartRenderWebGL();
                mandreelAppStartStateFunc.accept("ready", mandreelAppCanvasWidth, mandreelAppCanvasHeight);
            }
        }
    }

    public static void mandreelAppAudioReady() {
        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("audioLoaded", "", null);
        }
        mandreelAppStartReady();
    }
    private static void myOldConstructors(int Ptr, int size, int stackPos){
        int ptr = Ptr;
        ptr = ptr >> numDefine2;
        for (int i = 0; i < size; ++i) {
            int tag = heapClassInst.heap32[ptr];
            int ptrId = heapClassInst.heap32[ptr + 1];
            functionTable.get(ptrId >> numDefine2).accept(stackPos);
            ptr += numDefine2;
        }
    };
    public static void setupMandreel() {
        if (commonVariable.heapNewPos == numDefine512) {
//            registerDelegateInitialize(); // TODO :15文件里面注释掉的
//            CMalloc.malloc(); // TODO :CommonFile文件里面没有，但是写法和15文件注释掉的一个性质
        }
        swriteIndexInitialize();

//        myOldConstructors = mandreelCallConstructors;
        startMandreelTimer();
        startApp("");
        mandreelAppAudioReady();
    }

    public static void runMandreel() {
        commonVariable.mandreelCurrentTime = 0;
        int sp = gStackPointer + numDefine800 * numDefine1024;
        for (int i = 0; i < mandreelTotalMemory / numDefine4; i++) {
            heapClassInst.heap32[i] = heapClassInst.myHeap32.get(i);
        }
        TlsfPtr.tlsfPtr = 0;
        commonVariable.heapNewPos = myHeapNewPos;
        myOldConstructors(llvm2EGlobalCtors, numDefine5, sp);
        heapClassInst.heapU32[sp >> numDefine2] = (int) numDefine640;
        heapClassInst.heapU32[(sp + numDefine4) >> numDefine2] = (int) numDefine480;
        mandreelInternalSetResolution(sp);
        mandreelInternalInit(gStackPointer + numDefine800 * numDefine1024);
        initNew(gStackPointer + numDefine800 * numDefine1024);
        for (int i = 0; i < numDefine20; i++) {
            render();
            mandreelFlushTimeouts();
            updateMandreelStats((int) (System.currentTimeMillis() * 1000));
        }
        mandreelCheckState();
    }



    public static void startMandreelTimer() {
        commonVariable.mandreelSampleTimeStart = Timer.getTime();
    }

    public ArrayList<Double> latencyMandreel() {
        return commonVariable.mandreelPauseTimes;
    }

    public static void mandreelSetTimeout(Runnable cmd, double delay) {
        timeouts.add(cmd);
    }

    public static void mandreelFlushTimeouts() {
        while (mandreeltimeouts.size() != 0) {
            Object next = mandreeltimeouts.remove(mandreeltimeouts.size() - 1);
        }
    }

    public static void mandreelCheckState() {
        int sum = 0;
        for (int i = 0; i < heapClassInst.heap32.length; i += numDefine100) {
            sum = (int) ((sum * numDefine3 + heapClassInst.heap32[i]) & numDefine0xffffff);
        }
        deBugLog("sum: " + sum);
        if (sum != numDefine01026) {
            JOptionPane.showMessageDialog(null,"Check sum mismatch: expected ???, actual " + sum);
        }
    }

    public static void appStartState(String state, Object... param) {
        if (state.equals("loadingScript")) {
        }

        if (state.equals("scriptLoaded")) {
        }

        if (state.equals("loadingData")) {
        }

        if (state.equals("loadingAudio")) {
        }

        if (state.equals("audioLoaded")) {
        }

        if (state.equals("ready")) {
            MandreelBase canvasElement = mandreelDocument.getElementById("loading");
            if (canvasElement != null && canvasElement.style != null) {
                canvasElement.style.visibility = "hidden";
            }
        }

        if (state.equals("error")) {
            System.out.println(param.toString());
        }
    }

    public void mandreelSwfSizeLoaded(String str) {
        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("scriptLoaded", "", null);
        }
    }

    public void mandreelNextDecompress(LZMA mandreelResultLzma) {
        if (mandreelAppStartStateFunc != null) {
            int totalBytesLeft = mandreelResultLzma.totalSize - mandreelResultLzma.remainingBytes;
            int percentage;
            if (totalBytesLeft == 0) {
                percentage = 0;
            } else {
                percentage = (numDefine100 * totalBytesLeft) / mandreelResultLzma.totalSize;
            }
            mandreelAppStartStateFunc.accept("uncompressingDataUpdate", percentage, null);
        }

        LZMA oldResult = mandreelResultLzma;

        lzMA.decompressTwo(mandreelResultLzma.inStream, mandreelResultLzma.inStream, mandreelResultLzma.outStream, mandreelResultLzma);

    }

    public static void mandreelJsScriptLoaded() {
        if (mandreelJsScriptLoadedLoaded) {
            return;
        }

        if (mandreelCacheFiles.size() == 0) {
            mandreelSetTimeout(mandreelFile::mandreelJsScriptLoaded, numDefineFloat100);
            return;
        }

        mandreelJsScriptLoadedLoaded = true;

        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("scriptLoaded", "", null);
        }

        if (mandreelPackfiledataName != null) {
        } else {
            imandreelJsScriptLoaded();
        }
    }

    public static void imandreelLoadAudio() {

        commonVariable.gMandreelWorkingFolder = mandreelAppWorkingFolder;
        if (mandreelAppReadDataFromLocalHost) {
            commonVariable.gMandreelWorkingFolder = mandreelAppLocalHost + "/" + mandreelAppWorkingFolder;
        }

        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("loadingAudio", "", null);
        }
        mandreelStartAudio(mandreelAppHostedAudioServer, mandreelAppHostedAudioUrl);
    }

    public void imandreelUpdateLoad(int size, int total) {

        int total0 = total;
        if (total0 == 0) {
            total0 = mandreelPackfiledataSize + mandreelTotalPacktextureSize + variableSet.mandreelTotalPogfileSize + mandreelJslzmaSize + mandreelSwfSize;
        }

        mandreelUpdateTotalSize += size;

        int percentage = (numDefine100 * mandreelUpdateTotalSize) / total0;

        if (percentage > numDefine100) {
            percentage = numDefine100;
        }
        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("loadingProgress", percentage, null);
        }
    }


    public static void imandreelLoadNextTexturePack() {
        if (mandreelAppUsePackAsyncTexture.size() != 0) {
            mandreelCurrentPackTexture = mandreelAppUsePackAsyncTexture.remove(mandreelAppUsePackAsyncTexture.size() - 1);
        } else {
            imandreelLoadAudio();
        }
    }

    public static void imandreelJsScriptLoaded() {
        imandreelLoadNextTexturePack();
    }

    public void mandreelDecompressJSReady(String code, boolean saveFile) {
        if (saveFile) {
            mandreelFsSaveFile(mandreelAppMandreelJs + ".lzma", code);
        }

        MandreelElement ga = mandreelDocument.createElement("script");
        ga.type = "text/javascript";
        ga.text = code;

        MandreelElement s = mandreelDocument.getElementsByTagName("script")[0];
        s.parentNode.insertBefore(ga, s);
        s.parentNode.removeChild(ga);

        mandreelJsScriptLoaded();
    }

    public static void mandreelLoadCompressedJs(String codeJs) {
        // TODO: Implement code to load compressed JS
    }

    public static void mandreelLoadMandreelJsScript() {
        if (mandreelAppMandreelJsCompressed) {
            mandreelFsLoadText(mandreelAppMandreelJs + ".lzma", mandreelFile::mandreelLoadCompressedJs);
        } else {
            MandreelElement ga = mandreelDocument.createElement("script");
            ga.type = "text/javascript";
            ga.async = true;
            String url = mandreelAppMandreelJs;
            if (mandreelAppReadMandreelJsFromLocalHost) {
                ga.src = mandreelAppLocalHost + "/" + url;
            } else {
                ga.src = url;
            }
            MandreelElement s = mandreelDocument.getElementsByTagName("script")[0];
            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingScript", "", null);
            }
            s.parentNode.insertBefore(ga, s);
        }
    }

    public static void mandreelFatLoaded() {
        if (commonVariable.mandreelAppPlatform.equals("nacl")) {
            commonVariable.gMandreelWorkingFolder = mandreelAppWorkingFolder;
            if (mandreelAppReadDataFromLocalHost) {
                commonVariable.gMandreelWorkingFolder = mandreelAppLocalHost + "/" + mandreelAppWorkingFolder;
            }

            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingAudio", "", null);
            }
            mandreelAppAudioReady();
        } else {
            mandreelLoadMandreelJsScript();
        }
    }

    public static String mandreelRemovecr(String myString) {
        return "";
    }

    public static void mandreelAppInit() {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            globalInit(gStackPointer + numDefine800 * numDefine1024);
            globalInit1(gStackPointer + numDefine800 * numDefine1024);
            globalInit2(gStackPointer + numDefine800 * numDefine1024);
            globalInit3(gStackPointer + numDefine800 * numDefine1024);
            globalInit4(gStackPointer + numDefine800 * numDefine1024);
            globalInit5(gStackPointer + numDefine800 * numDefine1024);
            globalInit6(gStackPointer + numDefine800 * numDefine1024);
            globalInit7(gStackPointer + numDefine800 * numDefine1024);

            int sp = gStackPointer + numDefine800 * numDefine1024;
            heapClassInst.heapU32[sp >> numDefine2] = (int) mandreelAppCanvasWidth;
            heapClassInst.heapU32[(sp + numDefine4) >> numDefine2] = (int) mandreelAppCanvasHeight;
            mandreelInternalSetResolution(sp);
            mandreelInternalInit(gStackPointer + numDefine800 * numDefine1024);
            initNew(gStackPointer + numDefine800 * numDefine1024);
        }
    }

    public static void mandreelAppDraw(long elapsed) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int sp = gStackPointer + numDefine800 * numDefine1024;
            mandreelInternalPreupdate(sp);
            heapClassInst.heapU32[sp >> numDefine2] = (int) elapsed;
            draw(sp);
            mandreelInternalUpdate(sp);
            mandreelProcessAsyncCalls();
        }
    }

    public void mandreelAppMouseWheel(int delta) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = delta;
            mouseWheelDelta(i7);
            mandreelUnlockFrame();
        }
    }

    public void mandreelAppMouseMove(int x, int y) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = x;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = y;
            mouseMove(i7);
            mandreelUnlockFrame();
        }
    }

    public void mandreelAppResize(int x, int y) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = (int) x;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = (int) y;
            resize(i7);
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = (int) x;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = (int) y;
            mandreelInternalSetResolution(i7);
            mandreelUnlockFrame();
        }
    }

    public void mandreelAppMouseButton(int down, int x, int y) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = (int) down;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = (int) x;
            heapClassInst.heap32[(i7 + numDefine8) >> numDefine2] = (int) y;
            mouseButton(i7);
            mandreelUnlockFrame();
        }
    }

    public void mandreelAppMouseDblClick(int x, int y) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = (int) x;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = (int) y;
            mouseDoubleClick(i7);
            mandreelUnlockFrame();
        }
    }

    public void mandreelAppKeyEvent(int down, int keyId) {
        if (commonVariable.mandreelAppPlatform.equals("webgl") || commonVariable.mandreelAppPlatform.equals("canvas")) {
            int i7 = mandreelLockFrame();
            heapClassInst.heap32[(i7 + 0) >> numDefine2] = down;
            heapClassInst.heap32[(i7 + numDefine4) >> numDefine2] = keyId;
            keyEvent(i7);
            mandreelUnlockFrame();
        }
    }

    public String mandreelAppGetPlatform() {
        return commonVariable.mandreelAppPlatform;
    }

    public void mandreelWheel(MouseEvent event) {
        imandreelOnMouseWheel(event);
        event.preventDefault();
        event.returnValue = false;
    }

    public static void render() {
        long nowTime = dateNow();
        if (!gMandreelFrameLocked) {
            gMandreelFrameInframe = true;
            if (!imandreelPauseGame) {
                mandreelAppDraw(nowTime - imandreelOldTime);
            }
            gMandreelFrameInframe = false;
        }
        imandreelOldTime = nowTime;
    }

    public void imandreelOnMouseWheel(MouseEvent e) {
        if (!imandreelIsReady) {
            return;
        }
        if (imandreelPauseGame) {
            return;
        }

        mandreelAppMouseWheel((int) e.wheelDelta);
    }

    public void imandreelOnKeyUp(MouseEvent e) {
        if (!imandreelIsReady) {
            return;
        }
        if (imandreelPauseGame) {
            return;
        }
    }

    public void imandreelOnKeyDown(MouseEvent e) {

        if (e.which == numDefine8) {
            e.preventDefault();
        }
        if (!imandreelIsReady) {
            return;
        }
        if (imandreelPauseGame) {
            return;
        }
    }

    public void mandreelInterSwfLoaded() {
        appStartState("scriptLoaded", null);
        Param flashMovie = swfObject.getObjectById(mandreelAppCanvasDiv);
        dump(String.valueOf(flashMovie.width));
        flashMovie.mandreelInit();

        imandreelFlashGlobalSp = mandreelInterGetSWF.mandreelInterGetGlobalStack();
        imandreelFlashGlobalSp2 = mandreelInterGetSWF.mandreelInterGetGlobalStack2();
        if (mandreelAppStartStateFunc != null) {
            mandreelAppStartStateFunc.accept("ready", mandreelAppCanvasWidth, mandreelAppCanvasHeight);
        }
    }

    public String mandreelInterCallFunctionRaw(int sp, String funcName, String returnType) {
        return mandreelInterGetSWF.mandreelInterCallFunctionRaw(sp, funcName, returnType);
    }

    public boolean mandreelIsFilesystem() {
        if (mandreelIndexedDB.db != null) {
            return false;
        }

        if (variableSet.gMandreelFs != null) {
            return false;
        }

        return true;
    }

    public boolean mandreelIsIndexeddb() {
        if (mandreelIndexedDB.db != null) {
            return true;
        }

        return false;
    }

    public void mandreelFsSaveFile(String name, Object myArrayBuffer) {
    }

    public static void mandreelFsLoadText(String fileName, Consumer<String> callback) {
    }

    public void mandreelAppFullscreen(int enable) {
    }

    public void mandreelAppDisableForceFocus() {
        mandreelAppForceFocus = false;
    }

    public void mandreelAppEnableForceFocus() {
        mandreelAppForceFocus = true;
    }

    public String atob(String str) {
        return "";
    }

    public void imandreelAs3Dump(String param) {
        dump(atob(param));
    }

    public void pluginMandreelInterWriteInt(int ptr, int value) {
        mandreelEmbedPlugin.mandreelInterCalls("WriteInt", ptr, value);
    }

    public void pluginMandreelInterWriteFloat(int ptr, int value) {
        mandreelEmbedPlugin.mandreelInterCalls("WriteFloat", ptr, value);
    }

    public void pluginMandreelInterWriteString(int ptr, int value) {
        mandreelEmbedPlugin.mandreelInterCalls("WriteString", ptr, value);
    }

    public void pluginMandreelInterWriteWString(int ptr, int value) {
        mandreelEmbedPlugin.mandreelInterCalls("WriteWString", ptr, value);
    }

    public void pluginMandreelPause() {
        mandreelEmbedPlugin.mandreelInterCalls("Pause");
    }

    public void pluginMandreelResume() {
        mandreelEmbedPlugin.mandreelInterCalls("Resume");
    }


    public void pluginMandreelUnlockFrame() {
        mandreelEmbedPlugin.mandreelInterCalls("UnlockFrame");

        mandreelPluginCurrentSp -= numDefine300 * numDefine1024;
    }

    public void mandreelPluginDraw() {
        MandreelBase canvas = mandreelDocument.getElementById("canvasDiv");
        mandreelEmbedPlugin.mandreelInterCalls("AppDraw");
    }

    public static void mandreelInitPluginPlatform(Param params) {
    }

    public void mandreelInterSwfProgress(String mode, float percentage, int bytes, int totalbytes) {

        imandreelUpdateLoad(bytes, totalbytes);
        if (mode.equals("files")) {
            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingData", percentage, null);
            }
        } else if (mode.equals("audio")) {
            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingAudioUpdate", percentage, null);
            }
        } else if (mode.equals("textureasync")) {
            if (mandreelAppStartStateFunc != null) {
                mandreelAppStartStateFunc.accept("loadingTextureAsyncPack", percentage, null);
            }
        }
    }

    public void myAssert(int sp) {
        int sp0 = sp;
        int p0 = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int p1 = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        assert1(false, "hola");
    }

    public void writeHeapDouble(int addr, double value) {
        heapClassInst.heapDouble[addr >> numDefine3] = value;
    }

    public void writeHeapU64(int addr, HeapValue value) {
        heapClassInst.heap32[addr >> numDefine2] = (int) value.l;
        heapClassInst.heap32[(addr >> numDefine2) + 1] = (int) value.h;
    }

    public void z11printValued(String stackPos, String value) {
        System.out.println(value);
        System.out.println();
    }

    public void z11printLabelPKc(int stackPos, String addr) {
        System.out.println(stackPos + addr);
        System.out.println();
    }

    public void mallocSize(int sp) {
        int sp0 = sp;
        int ptr = heapClassInst.heapU32[sp0 >> numDefine2];
        sp0 -= numDefine4;

        heapClassInst.heap32[sp0 >> numDefine2] = ptr;
        tlsfBlockSize(sp0);
    }

    public void tlsfBlockSize(int sp) {
    }

    public void llvmMoveFloat(int addrDst, int addrSrc) {
        heapClassInst.heapU32[addrDst] = heapClassInst.heapU32[addrSrc];
    }

    public void log10f(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.log(value) / mandeelLog10;
    }

    public void log10(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.log(value) / mandeelLog10;
    }

    public void logf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.log(value);
    }

    public void log(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.log(value);
    }

    public void asinf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.asin(value);
    }

    public void asin(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.asin(value);
    }

    public void acos(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.acos(value);
    }

    public void floor(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.floor(value);
    }

    public void floorf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.floor(value);
    }

    public void round(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.round(value);
    }

    public void roundf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.round(value);
    }

    public void ceilf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.ceil(value);
    }

    public void ceil(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.ceil(value);
    }

    public void exp2(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.pow(2, value);
    }

    public void exp2f(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.pow(2, value);
    }

    public void pow(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        double value2 = heapClassInst.heapDouble[(sp + numDefine8) >> numDefine3];
        commonVariable.fg0 = Math.pow(value, value2);
    }

    public void cos(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.cos(value);
    }

    public void tan(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.tan(value);
    }

    public void expf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.exp(value);
    }

    public void tanf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.tan(value);
    }

    public void atanf(int sp) {
        float value = heapClassInst.heapFloat[sp >> numDefine2];
        commonVariable.fg0 = Math.atan(value);
    }

    public void atan(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.atan(value);
    }

    public void abs(int sp) {
        int value = heapClassInst.heap32[sp >> numDefine2];
        if (value < 0) {
            commonVariable.rg0 = -value;
        } else {
            commonVariable.rg0 = value;
        }
    }

    public void sin(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.sin(value);
    }

    public void sqrt(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.sqrt(value);
    }

    public void fmod(int sp) {
        int sp0 = sp;
        double value = heapClassInst.heapDouble[sp0 >> numDefine3];
        sp0 += numDefine8;
        double value2 = heapClassInst.heapDouble[sp0 >> numDefine3];
        commonVariable.fg0 = value % value2;
    }

    public void atan2(int sp) {
        double x = heapClassInst.heapDouble[sp >> numDefine3];
        double y = heapClassInst.heapDouble[(sp + numDefine8) >> numDefine3];
        commonVariable.fg0 = Math.atan2(x, y);
    }

    public void fabs(int sp) {
        double value = heapClassInst.heapDouble[sp >> numDefine3];
        commonVariable.fg0 = Math.abs(value);
    }

    public void z18OutputDebugStringAPKc(int sp) {
        puts(sp);
    }

    public void getenv(int sp) {
        commonVariable.rg0 = 0;
    }

    public boolean mandreelFcmpOrd(int X, int Y) {
        return (X == X && Y == Y);
    }

    public boolean mandreelFcmpUno(int X, int Y) {
        return (X != X || Y != Y);
    }

    public void mandreelRewind(int sp) {
        int sp0 = sp;
        int fileId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;

        fileIds.get(fileId).offset = 0;

        commonVariable.rg0 = 0;
    }

    public void mandreelGetc(int sp) {
        int sp0 = sp;
        int fileId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int offset = fileIds.get(fileId).offset;
        byte[] buffer = fileIds.get(fileId).buffer;

        byte[] byteArray = fileIds.get(fileId).byteArray;

        int total = 1;

        int result = 0;

        if ((offset + total) > buffer.length) {
            result = -1;
        } else {
            result = byteArray[offset];
            fileIds.get(fileId).offset += total;
        }
        commonVariable.rg0 = result;
    }

    public void llvmStoreUnalign32Float(String addr, double value) {
        heapClassInst.heapFloat[0] = (float) value;
        int data = heapClassInst.heap32[0];
        heapClassInst.heap8[Integer.parseInt(addr)] = (byte) (data & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + 1] = (byte) ((data >>> numDefine8) & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + numDefine2] = (byte) ((data >>> numDefine16) & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + numDefine3] = (byte) ((data >>> numDefine24) & numDefine0xff);
    }

    public void llvmStoreUnalign32(String addr, int value) {
        heapClassInst.heap8[Integer.parseInt(addr)] = (byte) (value & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + 1] = (byte) ((value >>> numDefine8) & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + numDefine2] = (byte) ((value >>> numDefine16) & numDefine0xff);
        heapClassInst.heap8[Integer.parseInt(addr) + numDefine3] = (byte) ((value >>> numDefine24) & numDefine0xff);
    }

    public byte llvmReadUnalign32(int addr) {
        byte value = 0;
        value = heapClassInst.heapU8[addr];
        value |= heapClassInst.heapU8[addr + 1] << numDefine8;
        value |= heapClassInst.heapU8[addr + numDefine2] << numDefine16;
        value |= heapClassInst.heapU8[addr + numDefine3] << numDefine24;
        return value;
    }

    public float llvmReadUnalign32Float(int addr) {
        byte value = 0;
        value = heapClassInst.heapU8[addr];
        value |= heapClassInst.heapU8[addr + 1] << numDefine8;
        value |= heapClassInst.heapU8[addr + numDefine2] << numDefine16;
        value |= heapClassInst.heapU8[addr + numDefine3] << numDefine24;

        heapClassInst.heap32[0] = (int) value;
        return heapClassInst.heapFloat[0];
    }

    public static void mandreelRenamels(int sp) {
        int sp0 = sp;
        int ptrName0 = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int ptrName1 = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;

        String key0 = getStringFromPtr(ptrName0);
        String key1 = getStringFromPtr(ptrName1);

        GetItemARR myLocalStorage = mandreelGetlocalstorage();

        String value = myLocalStorage.getItem(key0);
        String value2 = myLocalStorage.getItem(key1 + "size");

        if (value != null && value2 != null) {
            myLocalStorage.setItem(key1, value);
            myLocalStorage.setItem(key1 + "size", value2);

            myLocalStorage.removeItem(key0);
            myLocalStorage.removeItem(key0 + "size");
            commonVariable.rg0 = 0;
        } else {
            commonVariable.rg0 = -1;
        }
    }

    public static String getStringFromWptr(int ptr) {
        ptr >>= 1;
        StringBuilder ret = new StringBuilder();
        if (ptr == 0) {
            return ret.toString();
        }
        assert1((ptr & 1) == 0);
        int i = 0;
        while (true) {
            if (heapClassInst.heapU16[ptr + i] == 0) {
                break;
            }
            short t = heapClassInst.heapU16[ptr + i];
            ret.append(t);
            i += 1;
        }

        return ret.toString();
    }

    public static void fillWptrFromString(int ptr, String v) {
        ptr >>= 1;
        heapClassInst.heapU16[ptr] = 0;
    }

    public static int mandreelInterRetParam(String type, Object value) {

        switch (type) {
            case "int":
                commonVariable.rg0 = (int) value;
                break;
            case "float":
                commonVariable.fg0 = (double) value;
                break;
            default:
                assert1(false);
                break;
        }
        return 0;
    }

    public static Consumer<Integer> mandreelInterGetFunctionPtr(int value) {
        return functionTable.get(value >> numDefine2);
    }

    public void mandreelTextureAsyncCheckPending(int sp) {
        commonVariable.rg0 = mandreelTextureAsyncTextures - mandreelTextureAsyncTexturesLoaded;
    }

    public static void mandreelTextureAsyncGetProperties(int sp) {

        int sp0 = sp;
        int textureId = (int) heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int ptrWidth = (int) heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int ptrHeight = (int) heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;

        ArrayUniformLocations tex = arrayIdsOgl.get(textureId);

        if (tex == null || tex.mandreelWidth == 0) {
            commonVariable.rg0 = 0;
        } else {
            heapClassInst.heap32[ptrWidth >> 2] = (int) tex.mandreelWidth;
            heapClassInst.heap32[ptrHeight >> 2] = (int) tex.mandreelHeight;
            commonVariable.rg0 = 1;
        }
    }

    public static void mandreelInterWriteString(int ptr, String value) {
        fillPtrFromString(ptr, value);
    }

    public void mandreelInterWriteWString(int ptr, String value) {
        fillWptrFromString(ptr, value);
    }

    public void mandreelInterWriteFloat(int ptr, float value) {
        heapClassInst.heapFloat[ptr >> numDefine2] = value;
    }

    public void mandreelPause() {
        imandreelPauseGame = true;
    }

    public void mandreelResume() {
        imandreelPauseGame = false;
    }

    public int mandreelLockFrame() {
        assert1(gMandreelFrameInframe == false, "calling lockframe during render frame");
        assert1(gMandreelFrameLocked == false, "calling lockframe twice");
        gMandreelFrameLocked = true;

        return gStackPointer + numDefine800 * numDefine1024;
    }

    public void mandreelUnlockFrame() {
        assert1(gMandreelFrameInframe == false);
        gMandreelFrameLocked = false;
    }

    public void mandreelInterWriteInt(int ptr, int value) {
        heapClassInst.heap32[ptr >> numDefine2] = (int) value;
    }

    public String mandreelInterStringFromWPtr(int ptr) {
        return getStringFromWptr(ptr);
    }

    public String mandreelInterStringFromPtr(int ptr) {
        return getStringFromPtr(ptr);
    }

    public int[] mandreelMyCallExternalArray(String method, List<Object> params) {
        int result = 0;
        int resultString = 0;

        return new int[]{result, resultString};
    }

    public void mandreelInterjsCall(int sp) {
        int sp0 = sp;
        int methodPtr = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        String method = getStringFromPtr((int) methodPtr);
        List<Object> params = new ArrayList<>();
        params.add(sp0);

        int varInt = 0;
        String varString = "";
        double varDouble = 0.0;

        int returnType = 0;
        int returnPtr = 0;

        while (true) {
            int myType = heapClassInst.heap32[sp0 >> numDefine2];
            sp0 += numDefine4;

            if (myType == mandreelcalljsTypeReturnVoid) {
                returnType = myType;
                break;
            } else if (myType == mandreelcalljsTypeInt) {
                varInt = heapClassInst.heap32[sp0 >> numDefine2];
                params.add(varInt);
                sp0 += numDefine4;
            } else if (myType == mandreelcalljsTypeFloat) {
                sp0 = (sp0 + numDefine7) & ~numDefine7;
                varDouble = (double) llvmReadDouble(sp0);
                params.add(varDouble);
                sp0 += numDefine8;
            } else if (myType == mandreelcalljsTypeString) {
                varInt = heapClassInst.heap32[sp0 >> numDefine2];
                varString = getStringFromPtr(varInt);
                params.add(varString);
                sp0 += numDefine4;
            } else if (myType == mandreelcalljsTypeReturnInt) {
                returnType = myType;
                returnPtr = heapClassInst.heap32[sp0 >> numDefine2];
                break;
            } else if (myType == mandreelcalljsTypeReturnFloat) {
                returnType = myType;
                returnPtr = heapClassInst.heap32[sp0 >> numDefine2];
                break;
            } else {
                assert1(false, "invalid arguments calling mandreelInterjsCall");
            }
        }

        int[] result = mandreelMyCallExternalArray(method, params);
        commonVariable.rg0 = result[0];

        if (commonVariable.rg0 == 0) {
            if (returnType == mandreelcalljsTypeReturnInt) {
                heapClassInst.heap32[returnPtr >> numDefine2] = (int) result[1];
            } else if (returnType == mandreelcalljsTypeReturnFloat) {
                heapClassInst.heapFloat[returnPtr >> numDefine2] = (float) result[1];
            }
        }
    }

    public void mandreelInterJSAsyncCall(int sp) {
        int sp0 = sp;
        int methodPtr = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        String funcName = getStringFromPtr(methodPtr);
        int paramPtr = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        String param = getStringFromPtr(paramPtr);
        mandreelAsyncCallsJs.add(new FunClass(funcName, param));
    }

    public void mandreelInterCallFunctionAsync(String funcName, String param) {
        mandreelAsyncCallsMandreel.add(new FunClass(funcName, param));
    }

    public static void mandreelProcessAsyncCalls() {
        if (mandreelAsyncCallsMandreel.size() > 0) {
            List<FunClass> tempList = new ArrayList<>(mandreelAsyncCallsMandreel);

            mandreelAsyncCallsMandreel.clear();

            for (int i = 0; i < tempList.size(); i++) {
                String param = tempList.get(i).param;
                String funcName = tempList.get(i).funcName;

                long size = ((param.length() + 1) + numDefine7) & numDefine0xfffffff8;

                int sp = gStackPointer + numDefine800 * numDefine1024;

                int strPtr = sp - (int) size;
                fillPtrFromString(strPtr, param);

                sp = strPtr - numDefine4;
                heapClassInst.heap32[sp >> numDefine2] = strPtr;
            }
        }

        if (mandreelAsyncCallsJs.size() > 0) {
            List<FunClass> tempList = new ArrayList<>(mandreelAsyncCallsJs);

            mandreelAsyncCallsJs.clear();

            for (int i = 0; i < tempList.size(); i++) {
                String param = tempList.get(i).param;
                String funcName = tempList.get(i).funcName;
            }
        }
    }

    public void mandreelInternalIsCanvas(int sp) {
        if (commonVariable.mandreelAppPlatform.equals("canvas")) {
            commonVariable.rg0 = 1;
        } else {
            commonVariable.rg0 = 0;
        }
    }

    public void mandreelDeviceSetFullScreen(int sp) {
        int sp0 = sp;
        int enable = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        mandreelAppFullscreen(enable);
    }

    public void myglCreateUniformArrays() {
        if (uniformArraysCreated == 0) {
            for (int i = 0; i < numDefine256; i++) {
                uniformArrays2.addAll(Collections.nCopies(i * numDefine2, 0.0));
                uniformArrays3.addAll(Collections.nCopies(i * numDefine3, 0.0));
                uniformArrays4.addAll(Collections.nCopies(i * numDefine4, 0.0));
            }
            uniformArraysCreated = 1;
        }
    }

    public int myglNewSlot() {
        int id = mySuperId;
        mySuperId = mySuperId + 1;
        return id;
    }

    public void myglFreeSlot(int id) {
        arrayIdsOglEnable.add(id);
    }

    public void myglCreateTexture(int sp) {
        int id = myglNewSlot();
        commonVariable.rg0 = id;
    }

    public void myglCreateRenderBuffer(int sp) {
        int id = myglNewSlot();
        arrayIdsOgl.set(id, imandreelGl.createRenderbuffer());
        commonVariable.rg0 = id;
    }

    public void myglCreateFrameBuffer(int sp) {
        int id = myglNewSlot();
        arrayIdsOgl.set(id, imandreelGl.createFramebuffer());
        commonVariable.rg0 = id;
    }


    public void myglCreateBuffer(int sp) {
        int id = myglNewSlot();
        arrayIdsOgl.set(id, imandreelGl.createBuffer());
        commonVariable.rg0 = id;
    }

    public void myglGetShaderInfoLog(int sp) {
        int sp0 = sp;
        int programId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int ptrString = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        String infoLog = imandreelGl.getShaderInfoLog(arrayIdsOgl.get(programId));
        fillPtrFromString((int) ptrString, infoLog);
    }

    public void myglGetError(int sp) {
        commonVariable.rg0 = imandreelGl.getError();
        commonVariable.rg0 = 0;
    }

    public void myglGetProgramParameter(int sp) {
        int sp0 = sp;
        int programId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int pname = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        commonVariable.rg0 = imandreelGl.getProgramParameter(arrayIdsOgl.get(programId), (int) pname);
    }

    public void myglGetActiveAttrib(int sp) {
        int sp0 = sp;
        int programId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int index = heapClassInst.heap32[sp >> numDefine2];
        sp0 += numDefine4;
        int ptr = heapClassInst.heap32[sp >> numDefine2];
        sp0 += numDefine4;
        commonFile.ResultClass result = imandreelGl.getActiveAttrib(arrayIdsOgl.get(programId), (int) index);
        if (result != null) {
            heapClassInst.heap32[((int) ptr) >> numDefine2] = (int) result.size;
            heapClassInst.heap32[(((int) ptr) + numDefine4) >> numDefine2] = (int) result.type;
            fillPtrFromString(((int) ptr) + numDefine8, result.name);
            commonVariable.rg0 = 0;
        } else {
            commonVariable.rg0 = 1;
        }
    }

    public void myglGetActiveUniform(int sp) {
        int sp0 = sp;
        int programId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int index = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        int ptr = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        commonFile.ResultClass result = imandreelGl.getActiveUniform((arrayIdsOgl.get(programId)), (int) index);
        if (result != null) {
            heapClassInst.heap32[((int) ptr) >> numDefine2] = (int) result.size;
            heapClassInst.heap32[(((int) ptr) + numDefine4) >> numDefine2] = (int) result.type;
            fillPtrFromString(((int) ptr) + numDefine8, result.name);
            commonVariable.rg0 = 0;
        } else {
            commonVariable.rg0 = 1;
        }
    }

    public void mygetProgramParameter(int sp) {
        int sp0 = sp;
        int programId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int pname = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        commonVariable.rg0 = imandreelGl.getProgramParameter(arrayIdsOgl.get(programId), (int) pname);
    }

    public void mygetShaderParameter(int sp) {
        int sp0 = sp;
        int shaderId = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 = sp0 + numDefine4;
        int pname = heapClassInst.heap32[sp0 >> numDefine2];
        sp0 += numDefine4;
        commonVariable.rg0 = imandreelGl.getShaderParameter(arrayIdsOgl.get(shaderId), pname);
    }

    public void myglInit(int sp) {
        for (int i = 0; i < maxOglId; i++) {
            arrayIdsOglEnable.add(i + 1);
        }
    }

}

